#pragma once

#include "GpParameter.h"

namespace gp
{
	class ParameterBlock
	{
	public:

		ParameterBlock(Parameter* pParams, cr::size_t maxParams, cr::HashedString hsName = cr::HashedString())
		: m_hsName(hsName)
		, m_pParams(pParams)
		, m_numParams(0)
		, m_maxParams(maxParams)
		{
		}

		virtual ~ParameterBlock()
		{

		}

		void						SetName(cr::HashedString hsName)		{ m_hsName = hsName; }
		cr::HashedString			GetName() const							{ return m_hsName; }

		cr::size_t					GetNumParameters() const				{ return m_numParams; }
		void						Clear()									{ m_numParams = 0; }

		ParameterHandle				AddParameter()
		{
			CR_ASSERT(m_numParams < m_maxParams);
			return m_pParams[m_numParams++];
		}

		ParameterHandle				GetParameter(cr::size_t idxParameter)
		{
			CR_ASSERT(idxParameter < m_numParams);
			return m_pParams[idxParameter];
		}

	protected:

		cr::HashedString			m_hsName;
		Parameter*					m_pParams;
		cr::size_t					m_maxParams;
		cr::size_t					m_numParams;
	};

	typedef cr::Handle<ParameterBlock> ParameterBlockHandle;

	// ---------------------------------------------------------------------------------------------------------

	template <cr::size_t MAX_PARAMS>
	class ParameterBlockFixed : public ParameterBlock
	{
	public:

		ParameterBlockFixed(cr::HashedString hsName = cr::HashedString())
		: ParameterBlock(m_params, MAX_PARAMS, hsName)
		{

		}

	private:

		Parameter	m_params[MAX_PARAMS];
	};

	// ---------------------------------------------------------------------------------------------------------

	class ParameterBlockDynamic : public ParameterBlock
	{
	public:

		ParameterBlockDynamic(cr::size_t maxParams, cr::HashedString hsName = cr::HashedString())
		: ParameterBlock(new Parameter[maxParams], maxParams, hsName)
		{

		}

		~ParameterBlockDynamic()
		{
			delete [] m_pParams;
		}
	};

	// ---------------------------------------------------------------------------------------------------------

		namespace ParameterBlockScratchAllocator
		{
			void		ResetScratchParams();
			Parameter*	AllocateScratch(cr::size_t numParams);
		}

	template <cr::size_t MAX_PARAMS>
	class ParameterBlockScratch : public ParameterBlock
	{
	public:

		ParameterBlockScratch()
		:	ParameterBlock(ParameterBlockScratchAllocator::AllocateScratch(MAX_PARAMS), MAX_PARAMS)
		{

		}	
	};
}